<template>
	<div class="face-library">
		<div class="list-area">
			<div
				:key="index"
				v-for="(item, index) in typeList"
				class="list-item"
				:class="[activeIndex === index && 'active']"
				@click="changeList(index)"
			>
				{{ item }}
			</div>
		</div>
		<div class="data-right">
			<!-- 标题头 -->
			<div class="data-header">
				<div class="header-title">人脸库-{{ activeIndex === 1 ? '白名单' : '黑名单' }}</div>
				<div class="header-operation">
					<a-dropdown placement="bottomLeft">
						<a-button v-auth="'ai-service-edit'" type="primary" class="alone-icon-button">
							<i class="iconfont icon-add-line"></i>
						</a-button>
						<template #overlay>
							<a-menu>
								<a-menu-item @click="handleAddFace">添加</a-menu-item>
								<a-menu-item @click="handleAddImage">批量上传</a-menu-item>
							</a-menu>
						</template>
					</a-dropdown>
				</div>
			</div>
			<!-- 数据区 -->
			<div class="data-area" :style="{ paddingBottom: showCheckbox ? '64px' : '16px' }">
				<vue-scroll @handle-scroll="handlePageScroll">
					<a-spin :spinning="tableAttr.loading">
						<global-img-list-upload
							v-model:value="tableAttr.data"
							v-model:checked-list="checkedList"
							:dpi="[
								[96, 96],
								[2048, 1080]
							]"
							:show-name="true"
							:show-add="false"
							:max-file-size="10"
							:show-checkbox="showCheckbox"
							:module-type="ModuleType.AI_FACE"
							:disabled-update-upload="true"
							:disabled-delete="true"
							:readonly="false"
							:show-checkbox-hover="true"
							@on-remove="onRemoveImage"
							@on-update="onUpdateFace"
							@on-checked-change="onCheckedChange"
						></global-img-list-upload>
					</a-spin>
					<!-- :readonly="!checkKey('ai-service-edit')" -->
				</vue-scroll>
			</div>
			<!-- 分页区 -->
			<div class="suspend">
				<div v-if="showCheckbox" class="suspend-operate">
					<div class="suspend-operate-select">
						<a-checkbox v-model:checked="checkAll" @change="handleCheckAll">全选本页</a-checkbox>
						<span></span>
						<p :style="{ color: checkedList.length > 0 ? 'rgba(240, 246, 252, 1)' : 'rgba(48, 93, 194, 1)' }">
							已选中{{ checkedList.length }}条
						</p>
					</div>
					<span class="export-line"></span>
					<div class="selecting-data-operate-operate">
						<a-button
							type="default"
							class="icon-button"
							:disabled="checkedList.length === 0"
							:loading="deleteFaceLoading"
							@click="deleteFace(checkedList)"
						>
							<!-- <i class="iconfont icon-delete-bin-6-line"></i> -->
							<global-svg-icon icon-name="delete-bin-line" width="16px" height="16px" style="margin-top: 2px"></global-svg-icon>
							删除
						</a-button>
					</div>
				</div>
				<div class="suspend-pagination">
					<a-button type="default" class="icon-button" :class="[!showCheckbox && 'icon-select-button']" @click="handleOpenSelect">
						<global-svg-icon
							v-if="showCheckbox"
							icon-name="arrow-down-s-line"
							width="16px"
							height="16px"
							style="margin-right: 6px"
						></global-svg-icon>
						<global-svg-icon v-else icon-name="icon-wrapper" width="16px" height="16px" style="margin-right: 6px"></global-svg-icon>

						选择
					</a-button>

					<div class="pagination">
						<global-pagination
							:current="tableAttr.current"
							:page-size="tableAttr.pageSize"
							:total="tableAttr.total"
							:page-size-options="['50', '100', '200']"
							@change="setTablePagination"
						></global-pagination>
					</div>
				</div>
			</div>
		</div>
		<a-modal
			v-if="faceFormVisible"
			v-model:open="faceFormVisible"
			:centered="true"
			width="600px"
			destroy-on-close
			:title="faceFormTitle"
			:mask-closable="false"
			:confirm-loading="faceFormLoading"
			:body-style="{ padding: '40px 62px 20px' }"
			@ok="onFaceSubmit"
		>
			<a-form ref="faceFormRef" class="modal-form" :model="faceForm" layout="vertical" :rules="faceRules">
				<span class="face-form-line"></span>
				<div class="upload-image-wrap">
					<div class="list-upload">
						<a-form-item name="relativeFilePath">
							<global-img-list-upload
								v-model:value="faceForm.relativeFilePath"
								:dpi="[
									[96, 96],
									[2048, 1080]
								]"
								accept="bmp,jpeg,png,jpg"
								:count="1"
								:box-serial="boxSerial"
								placeholder="上传照片"
								:module-type="ModuleType.AI_FACE"
								:max-file-size="10"
								size="large"
							></global-img-list-upload>
						</a-form-item>
					</div>
					<div>
						<p>上传照片要求：</p>
						<p><span>1.</span>人脸照片应该清晰、无遮挡、无模糊、无变形，确保能够准确识别出人脸特征；</p>
						<p><span>2.</span>至少96*96像素，最大2048*1080像素，最大不超过10MB；</p>
						<p><span>3.</span>图片格式JPG、PNG、BMP、JPEG</p>
					</div>
				</div>
				<a-form-item label="人员名称" name="personName">
					<a-input v-model:value="faceForm.personName" :maxlength="20" style="width: 320px" placeholder="请输入"></a-input>
				</a-form-item>
				<a-form-item class="mt-24" label="人员类型" name="type">
					<a-radio-group v-model:value="faceForm.type" option-type="default">
						<a-radio :value="1">白名单</a-radio>
						<a-radio :value="0">黑名单</a-radio>
					</a-radio-group>
				</a-form-item>
				<div class="flex" style="gap: 0 80px">
					<a-form-item label="性别" class="mt-24" name="sex">
						<a-radio-group v-model:value="faceForm.sex">
							<a-radio :value="0">男</a-radio>
							<a-radio :value="1">女</a-radio>
						</a-radio-group>
					</a-form-item>
				</div>
			</a-form>
		</a-modal>

		<!-- 批量上传 -->
		<upload-select-modal
			v-model:visible="visible"
			:dpi="[
				[96, 96],
				[2048, 1080]
			]"
			accept="bmp,jpeg,png,jpg"
			:max-file-size="10"
			title="上传人脸照片要求："
			:box-serial="boxSerial"
			:on-success="onSuccess"
			:type="activeIndex"
			:module-type="ModuleType.AI_FACE"
			:before-upload="beforeUpload"
			@on-cancel="onSelectModalCancel"
		>
			<template #subTitle>
				<div class="sub-title">
					<p><span>1.</span>照片应该清晰、无遮挡、无模糊、无变形，确保能够准确识别出人脸特征；</p>
					<p><span>2.</span>至少96*96像素，最大2048*1080像素，最大不超过10MB；</p>
					<p><span>3.</span>图片格式JPG、PNG、BMP、JPEG</p>
					<p><span>4.</span>批量导入单次不超过100张</p>
					<p>
						<span>5.</span
						>文件名为【人员姓名_性别】，例如【张三.jpg】。如果姓名中包含空格或特殊字符，请使用下划线代替。性别可用_男/_女添加在照片最后，检测到格式则使用对应性别，未检测到则默认男性
					</p>
				</div>
			</template>
		</upload-select-modal>
	</div>
</template>

<script setup lang="ts" name="face-library">
import { FormInstance, message } from 'ant-design-vue';
import { Rule } from 'ant-design-vue/es/form';
import { g6UseTable } from 'glasssix-vue3-hooks';
import { getFileName } from '@/global-utils/base.utils';
import { chineseAndNumberAndLetterReg } from '@/global-utils/check';
import { BoxManageApi } from '../../../../api';
import { FileList } from '../../../../type';
import { UploadSelectModal } from '../../../index';

type TsProps = {
	serverId?: number;
};
const props = withDefaults(defineProps<TsProps>(), {
	serverId: 0
});

const typeList = ref<string[]>(['黑名单', '白名单']);
const activeIndex = ref<number>(1);
const $message: any = inject('$message');
const route = useRoute();
const { tableAttr, setTableData, setTablePagination } = g6UseTable(BoxManageApi.faceRecognitionList, { pageSize: 50 });

// 盒子序列号
const boxSerial = ref<string>('');
/**
 * 新增/修改人脸
 */
const faceFormLoading = ref<boolean>(false);
const faceFormVisible = ref<boolean>(false);
const faceFormTitle = ref<string>('添加');
const faceFormRef = ref<FormInstance>();
const faceForm = ref<any>({
	personName: '',
	sex: 0,
	age: 0,
	imageUrl: [],
	relativeFilePath: [],
	type: 1
});
const faceRules: Record<string, Rule[]> = {
	personName: [
		{
			required: true,
			message: '请输入名称',
			trigger: 'blur'
		},
		{
			pattern: chineseAndNumberAndLetterReg,
			message: '请输入汉字、数字或字母',
			trigger: 'blur'
		}
	],
	relativeFilePath: [
		{
			type: 'array',
			required: true,
			message: '请上传图片'
		}
	]
};
// 添加
const handleAddFace = (): void => {
	faceForm.value = {
		sex: 0,
		type: 1,
		imageUrl: [],
		relativeFilePath: [],
		personName: ''
	};
	faceFormRef.value?.resetFields();
	faceFormTitle.value = '添加';
	faceFormVisible.value = true;
};
const onFaceSubmit = async (): Promise<void> => {
	try {
		faceFormLoading.value = true;
		await faceFormRef.value?.validate();
		console.log('faceForm:', faceForm.value);

		const params = {
			// ...faceForm,
			personName: faceForm.value.personName,
			type: faceForm.value.type,
			sex: faceForm.value.sex,
			bAiServerId: props.serverId,
			id: faceForm.value.id,
			boxSerial: boxSerial.value,
			imageUrl: faceForm.value.relativeFilePath[0].imageUrl
		};
		let res: TsRes = {};
		if (faceFormTitle.value === '添加') {
			res = await BoxManageApi.savePersonInfo(params);
		} else {
			res = await BoxManageApi.updatePersonInfo(params);
		}
		if (res.code === 0) {
			tableAttr.current = 1;
			setTableData();

			faceForm.value = {};
			faceForm.value.relativeFilePath = [];
			message.success('操作成功');
			faceFormVisible.value = false;
		}
		faceFormLoading.value = false;
	} catch (error) {
		console.error(error);
	}
};
// 打开上传弹窗
const visible = ref<boolean>(false);

const handleAddImage = (): void => {
	visible.value = true;
};

/**
 * 选中的列表
 */
// 列表数据
// 多选图片
const showCheckbox = ref<boolean>(false);

const checkedList = ref<any[]>([]);
// const showCheckbox = ref<boolean>(false);
const checkAll = ref<boolean>(false);
// const exportDisabled = ref<boolean>(false);

const headerBottomBorderColor = ref('transparent');
enum ModuleType {
	SYSTEM = 0, // 系统Logo
	SYSTEM_SOFTWARE_UPGRADE = 1, // 系统软件升级
	SYSTEM_HARDWARE_UPGRADE = 2, // 系统硬件升级
	AI_UNIFORM = 3, // AI工服库接口
	AI_FACE = 4, // AI人脸接口
	AI_SDK = 7 // AI服务接口`
}
const handlePageScroll = (vertical: Record<string, any>): void => {
	headerBottomBorderColor.value = vertical.scrollTop > 10 ? '#20305b' : 'transparent';
};
/**
 * 删除人脸
 */
const openSelect = ref<boolean>(false);
const deleteFaceLoading = ref<boolean>(false);
const deleteFace = async (ids: number[]): Promise<void> => {
	deleteFaceLoading.value = true;
	const pramas = {
		ids,
		boxSerial: boxSerial.value
	};
	const res: TsRes = await BoxManageApi.deletePersonInfo(pramas);
	console.log('res:', res);

	if (res.code === 0) {
		$message.success('操作成功');
		checkedList.value = [];
		showCheckbox.value = false;
		openSelect.value = false;
		setTableData();
		deleteFaceLoading.value = false;
	}
};
const onRemoveImage = (item: FileList): void => {
	item.status = 'loading';
	deleteFace([item.id as number]);
};

// 修改人脸
const onUpdateFace = (item: any, index: number): void => {
	faceFormTitle.value = '修改';
	faceFormVisible.value = true;
	const data: any = tableAttr.data[index];

	faceForm.value = data;
	faceForm.value.relativeFilePath = [
		{
			id: item.id,
			personName: item.personName,
			imageUrl: item.imageUrl,
			originalUrl: data.imageLocation
		}
	];
};

const onCheckedChange = (): void => {
	showCheckbox.value = true;
	checkAll.value = checkedList.value.length === tableAttr.data.length;
};

// 全选、反选
const handleCheckAll = (e: any): void => {
	checkAll.value = e.target.checked;
	if (checkAll.value) {
		checkedList.value = tableAttr.data.map((item: any) => item.id);
	} else {
		checkedList.value = [];
	}
};

const handleOpenSelect = (): void => {
	showCheckbox.value = !showCheckbox.value;
	checkedList.value = [];
	checkAll.value = false;
};

const changeList = (index: number): void => {
	activeIndex.value = index;
	tableAttr.searchObj.type = index;
	setTableData();
};

const beforeUpload = (file: File): Promise<boolean> => {
	console.log('file.name:', file.name);

	if (chineseAndNumberAndLetterReg.test(getFileName(file.name))) {
		return Promise.resolve(true);
	}
	return Promise.reject('名称格式错误');
};
// 上传成功后的回调,用于发起业务请求
const onSuccess = async (res: any): Promise<void> => {
	tableAttr.current = 1;
	console.log('上传成功后的回调,用于发起业务请求:', res);

	// return aiApi.addFace({
	// 	type: 1,
	// 	imageUrl: res.imageUrl,
	// 	name: getFileName(res.name)
	// });
};
// 关闭上传弹窗
const onSelectModalCancel = (): void => {
	showCheckbox.value = false;
	tableAttr.current = 1;

	setTableData();
};

onMounted(() => {
	tableAttr.searchObj.type = activeIndex.value;
	boxSerial.value = route.query?.boxSerial as string;
	tableAttr.searchObj.boxSerial = boxSerial.value;
	setTableData();
});
</script>

<style lang="less" scoped>
// 弹窗
.face-library {
	display: flex;
	overflow: hidden;
	height: 600px;
	border: 1px solid @borderColor02;
	border-radius: 4px;

	.list-area {
		width: 180px;
		border-right: 1px solid @borderColor02;
		padding: 16px;
		background: #131e33;

		.list-item {
			height: 36px;
			margin-bottom: 8px;
			padding: 0 12px;
			line-height: 36px;
			color: @text02;
			cursor: pointer;

			&.active {
				border-radius: 6px;
				color: @text01;
				background: @mask02;
			}
		}
	}

	.data-right {
		// flex-direction: column;
		position: relative;
		flex: 2;

		.data-header {
			display: flex;
			justify-content: space-between;
			height: 68px;
			border-bottom: 1px solid @borderColor01;
			padding: 16px;
			font-size: 16px;
			font-weight: 700;
			font-style: normal;
			line-height: 24px;
			color: @text02;
			background: @background02;
		}

		.data-area {
			overflow: scroll;
			height: 484px;
			padding: 16px;
		}

		.card-wrap {
			// overflow: auto;
			// overflow-y: scroll;
			// width: calc(100vw - var(--side-width) - 98px);
			width: 100%;
			height: 100%;
			flex: 1;

			.ant-spin-nested-loading {
				position: absolute;
				top: 12px;
				// z-index: 9999;
				// display: flex;
				width: 100%;
				height: 100%;

				.ant-spin-dot {
					margin: 0;
				}
				// border-radius: 6px;
				// background-color: rgba(23, 40, 69, 0.96);
				// transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
				// align-items: center;
				// justify-content: center;
				// backdrop-filter: saturate(244%) blur(5px);
			}

			:deep(.ant-checkbox-inner) {
				border-color: rgba(217, 217, 219, 1) !important;
				background-color: @white !important;
			}

			:deep(.ant-checkbox-checked) {
				.ant-checkbox-inner {
					background: @primary01;
				}
			}

			.card-list {
				// flex-wrap: wrap;
				display: grid;
				// display: flex;
				overflow: hidden;
				// width: calc(100vw - var(--side-width) - 9px);
				width: 100%;
				height: 100%;
				padding-right: 32px;
				grid-template-columns: repeat(8, 1fr);
				grid-template-rows: repeat(2, 1fr);
				grid-column-gap: 20px;
				/* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */
				grid-row-gap: 20px;

				.lastLine {
					margin-right: 0;
				}

				.card-list-item {
					position: relative;
					height: 220px;
					border: 1px solid transparent;
					border-radius: 6px;
					padding: 4px 6px;
					cursor: pointer;

					.img-wrap {
						width: 100%;
						height: 114px;

						> img {
							width: 100%;
							height: 100%;
							object-fit: cover;
							border-radius: 4px;
						}
					}

					.info-box {
						overflow: hidden; /* 隐藏超出容器的内容 */
						white-space: nowrap; /* 防止换行 */
						text-overflow: ellipsis; /* 当文字超出容器时显示省略号 */
						color: @text03;

						.ai-item {
							display: flex;
							margin-top: 6px;
							font-size: 12px;
							color: @text01;
							justify-content: space-between;

							.ai-alarm-name {
								border-radius: 4px;
								padding: 0 6px;
								font-family: 'Alimama FangYuanTi VF';
								line-height: 20px;
								background: @secondary03;
								text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
							}

							.sence-name {
								line-height: 20px;
							}
						}

						.info-item {
							line-height: 20px;
							color: @text03;
						}

						.time-item {
							color: @text04;
						}
					}

					.tag {
						margin-left: auto;
						border: 1px solid rgba(0, 0, 0, 0.12);
						border-radius: 4px;
						padding: 0 6px;
						font-size: 12px;
						white-space: nowrap;
						color: #d67900;
						background: rgba(245, 151, 0, 0.12);
					}

					.right-top {
						position: absolute;
						top: 6px;
						right: 8px;

						.ant-checkbox-inner {
							background: #fff !important;
						}
					}

					&:hover,
					&.checked {
						border: 1px solid #374b79;
						// background-color: #fff;
						// box-shadow:
						// 	0 2px 8px 0 rgba(37, 37, 45, 0.14),
						// 	0 1px 3px 0 rgba(37, 37, 45, 0.14);
						border-radius: 8px;
						background: radial-gradient(66.29% 107.13% at 0% 0%, rgba(38, 62, 131, 0.12) 0%, rgba(217, 217, 217, 0.02) 100%), #0f224e;
						box-shadow: 0 3px 16px 0 rgba(0, 0, 0, 0.25);

						.right-top {
							display: block !important;
						}

						&::before {
							position: absolute;
							top: 0;
							left: 0;
							width: 100%;
							height: 100%;
							content: '';
							// background-color: rgba(0, 0, 0, 0.08);
						}
					}
				}
			}
		}

		.suspend {
			box-sizing: content-box;
			position: absolute;
			bottom: 0;
			left: 0;
			z-index: 9;
			width: 100%;
			border-top: 1px solid @borderColor01;
			border-bottom-right-radius: 8px;
			border-bottom-left-radius: 8px;
			background: @background02;
			box-shadow:
				0 -1px 3px rgba(37, 37, 45, 0.14),
				0 -2px 8px rgba(37, 37, 45, 0.14);

			.suspend-operate {
				display: flex;
				align-items: center;
				height: 48px;
				border-bottom: 1px solid @borderColor01;
				padding-left: 24px;

				.suspend-operate-select {
					display: flex;
					align-items: center;

					:deep(.ant-checkbox-wrapper) {
						span {
							color: @text01 !important;
						}
					}

					p {
						font-size: 14px;
						font-weight: 400;
						color: @primary01;
					}

					span {
						display: block;
						width: 1px;
						height: 20px;
						margin: 0 24px;
						background: #d9d9db;
					}
				}

				.export-line {
					display: block;
					width: 1px;
					height: 38px;
					margin: 0 32px;
					background: @borderColor02;
				}

				.suspend-operate-btns {
					display: flex;
					height: 100%;
					// border-left: 1px solid @borderColor02;
					padding-left: 24px;
					align-items: center;
					gap: 0 12px;
				}
			}

			.suspend-pagination {
				display: flex;
				height: 48px;
				padding: 0 24px;
				color: @text01;
				align-items: center;
				box-shadow: 0 -1px 8px 0 rgba(0, 0, 0, 0.25);

				.icon-button {
					width: 82px;
					height: 36px;
				}

				.pagination {
					margin: 0 auto;
					margin-top: -10px;
				}

				.icon-select-button {
					background-color: rgba(0, 0, 0, 0.1);
				}
			}
		}
	}
}

.modal-form {
	input {
		width: 328px;
	}

	.face-form-line {
		display: block;
		width: 100%;
		height: 1px;
		margin-bottom: 28px;
		background-color: @borderColor01;
	}

	.ant-radio-group {
		.ant-radio-wrapper {
			border: none;
			padding: 0;
		}

		.ant-radio-wrapper-checked {
			border: none;
		}
	}

	.upload-image-wrap {
		display: flex;
		margin-bottom: 24px;
		border-bottom: 1px solid @borderColor02;
		padding-bottom: 24px;
		// gap: 0 18px;
		.list-upload {
			margin-right: 13px;
		}

		p {
			display: flex;
			margin: 0;
			font-size: 12px;
			line-height: 20px;
			color: @text03;

			span {
				margin-right: 4px;
			}

			&:first-child {
				margin-bottom: 8px;
			}
		}
	}

	.mt-24 {
		margin-top: 24px;
	}
}
</style>
